﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Disposables;
using System.Linq;
using System.Linq.Expressions;
using SoftSource.Common;
using SoftSource.Timecard.Web.Data;

namespace SoftSource.Timecard.ReportDataClasses
{
    public sealed class ProjectStartEndDateReportTemplateData : INotifyPropertyChanged
    {
        private MutableDisposable mutable;

        public ProjectStartEndDateReportTemplateData()
        {
            this.mutable = new MutableDisposable();
            this.Projects = new ObservableCollection<ProjectSummary>();
            this.Projects.Populate(App.Model.ProjectSummaries.Entities
                .Where(p => p.StatusID == ProjectStatus.Active)
                .OrderBy(p => p.Name));
            this.EndDate = DateTime.Now;
            this.StartDate = this.EndDate.AddYears(-1);
        }        

        public ObservableCollection<ProjectSummary> Projects { get; set; }

        private bool thisWeek;
        public bool ThisWeek
        {
            get { return this.thisWeek; }
            set
            {
                if (this.thisWeek == value)
                    return;

                this.thisWeek = value;

                this.StartDate = DateTime.Now.StartOfWeek(DayOfWeek.Sunday);
                this.EndDate = this.StartDate.AddDays(7);

                this.thisMonth = false;
                this.PropertyChanged.Notify(() => this.ThisMonth);

                this.thisYear = false;
                this.PropertyChanged.Notify(() => this.ThisYear);

                this.projectToDate = false;
                this.PropertyChanged.Notify(() => this.ProjectToDate);

                this.PropertyChanged.Notify(() => this.ThisWeek);
            }
        }

        private bool thisMonth;
        public bool ThisMonth
        {
            get { return this.thisMonth; }
            set
            {
                if (this.thisMonth == value)
                    return;

                this.thisMonth = value;

                var now = DateTime.Now;
                this.StartDate = new DateTime(now.Year, now.Month, 1);
                this.EndDate = this.StartDate.AddMonths(1).AddDays(-1);

                this.thisWeek = false;
                this.PropertyChanged.Notify(() => this.ThisWeek);

                this.thisYear = false;
                this.PropertyChanged.Notify(() => this.ThisYear);

                this.projectToDate = false;
                this.PropertyChanged.Notify(() => this.ProjectToDate);

                this.PropertyChanged.Notify(() => this.ThisMonth);
            }
        }

        private bool thisYear;
        public bool ThisYear
        {
            get { return this.thisYear; }
            set
            {
                if (this.thisYear == value)
                    return;

                this.thisYear = value;

                var now = DateTime.Now;
                this.StartDate = new DateTime(now.Year, 1, 1);
                this.EndDate = this.StartDate.AddYears(1).AddDays(-1);

                this.thisWeek = false;
                this.PropertyChanged.Notify(() => this.ThisWeek);

                this.thisMonth = false;
                this.PropertyChanged.Notify(() => this.ThisMonth);

                this.projectToDate = false;
                this.PropertyChanged.Notify(() => this.ProjectToDate);

                this.PropertyChanged.Notify(() => this.ThisYear);
            }
        }

        private bool projectToDate;
        public bool ProjectToDate
        {
            get { return this.projectToDate; }
            set
            {
                if (this.projectToDate == value)
                    return;

                this.projectToDate = value;

                this.thisWeek = false;
                this.PropertyChanged.Notify(() => this.ThisWeek);

                this.thisMonth = false;
                this.PropertyChanged.Notify(() => this.ThisMonth);

                this.thisYear = false;
                this.PropertyChanged.Notify(() => this.ThisYear);

                this.SetProjectToDate();
                this.PropertyChanged.Notify(() => this.ProjectToDate);
            }
        }

        private void SetProjectToDate()
        {
            if (this.projectToDate && this.ProjectID > 0)
            {
                var getCreationDateDisposable = App.Model.GetProjectCreationDate(this.ProjectID)
                    .Do(date => this.StartDate = date)
                    .Do(date => this.EndDate = DateTime.Now)
                    .Subscribe();
                this.mutable.Replace(getCreationDateDisposable);
            }
        }

        #region Parameters
        private int projectID;
        [Parameter]
        public int ProjectID
        {
            get { return this.projectID; }
            set
            {
                this.projectID = value;
                this.SetProjectToDate();
                this.PropertyChanged.Notify(() => this.ProjectID);
            }
        }

        private DateTime startDate;
        [Parameter]
        public DateTime StartDate
        {
            get { return this.startDate; }
            set
            {                
                this.startDate = value;
                this.PropertyChanged.Notify(() => this.StartDate);
            }
        }

        private DateTime endDate;
        [Parameter]
        public DateTime EndDate
        {
            get { return this.endDate; }
            set
            {
                this.endDate = value;
                this.PropertyChanged.Notify(() => this.EndDate);
            }
        }
        #endregion Parameters

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}
